﻿define([],
function () {
    'use strict';

    return {

        /* Test for types */
        isDefined: function (o) {
            return typeof o != 'undefined' && o !== null;
        },

        isString: function (o) {
            return typeof o == 'string';
        },

        isArray: function (o) {
            return this.isDefined(o) && (o.constructor == Array);
        },

        isDomNode: function (o) {
            return this.isDefined(o) && this.isDefined(o.nodeType);
        },

        isFunction: function (o) {
            return typeof o === 'function';
        },

        isEmpty: function (o) {
            return Object.keys(o).length === 0;
        },

        isPrimitive: function (o) {
            return typeof o == 'undefined'
                || typeof o == 'null'
                || typeof o == 'boolean'
                || typeof o == 'string'
                || typeof o == 'number';
        },

        // Compares two objects for equality
        isEquivalent: function (o1, o2) {

            throw 'Not implemented';
        },

        /* Style */
        // Converts a style string to a javascript object
        parseStyle: function (style) {

            if (this.isPrimitive(style)) {

                var o = {};

                return o;
            }

            return style;
        },

        styleToString: function (style) {

            if (this.isString(style)) {
                return style;
            }

            var str = '';
            for (var key in style) {
                str += key + ':' + style[key] + ';';
            }

            return str;
        },

        /* Inheritance */
        // Assign members from to. Existing members will NOT be ovewriten
        augment: function (to, from) {
            for (var member in from) {
                if (!to[member]) {
                    to[member] = from[member];
                }
            }
        },

        // Extends the derived constructor method from the base one
        extend: function (derived, base) {
            derived.prototype = Object.create(base.prototype);
            derived.prototype.constructor = derived;
            derived.base = base.prototype;

            if (base.prototype.constructor == Object.prototype.constructor) {
                base.prototype.constructor = base;
            }
        },

        // Creates a constructor function from a configuration object
        define: function (conf) {
            var ctor = conf.construct || function () { }; // constructor is an existing method of Object.prototype therefore we give a different name ('construct') in the configuration object

            if (conf.base) {
                this.extend(ctor, conf.base);
            }

            if (conf.mixins) {

                ctor.mixins = []; // Store the mixins

                conf.mixins.forEach(function (mixin) {
                    if (mixin) {
                        this.augment(ctor.prototype, mixin.prototype);
                    }

                    ctor.mixins.push(mixin);
                },
                this);
            }

            for (var key in conf) {
                if (key != 'construct'
                    && key != 'base'
                    && key != 'mixins') {
                    ctor.prototype[key] = conf[key];
                }
            }

            return ctor;
        },

        toCamelCase: function (s) {
            if (s) {
                return s[0].toLowerCase() + s.substring(1);
            }

            return s;
        },

        toPascalCase: function (s) {
            if (s) {
                return s[0].toUpperCase() + s.substring(1);
            }

            return s;
        },

        // Tests whether the string s contains the word w
        contains: function (s, w, sep) {

            if (!s) {
                return false;
            }

            var sep = sep || ' ',
                words = s.split(sep);

            for (var i = 0; i < words.length; ++i) {
                if (words[i] === w) {
                    return true;
                }
            }

            return false;
        }
    };
});